package com.boot.mybatis.service;

import com.boot.mybatis.entity.Account;
import com.boot.mybatis.mapper.AccountMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class AccountService {
    @Autowired
    private AccountMapper accountMapper;

    public int add(String name, double money) {
        return accountMapper.add(name, money);
    }
    public int update(String name, double money, int id) {
        return accountMapper.update(name, money, id);
    }


    public int delete(int id) {
        return accountMapper.delete(id);
    }
    public Account findAccount(int id) {
        return accountMapper.findAccount(id);
    }
    public List<Account> findAccountList() {
        return accountMapper.findAccountList();
    }

    /**
     * 添加金钱
     * @param id
     * @param money 需要添加的钱，传负数时，为减去
     * @return
     */
    public int addMoney(int id,double money) {
        Account account = accountMapper.findAccount(id);
        account.setMoney(account.getMoney() + money);
        int count = accountMapper.update(account.getName(), account.getMoney(), account.getId());
        return count;
    }


    // id1支付给id2，测试时，只要id2不存在，就会异常，id1的钱也不会少
    // 最常用的事务处理方式，不捕获异常，事务会生效
    // 只要是RuntimeException，都会被捕获，比如NullPointerException是子类
    @Transactional
    public String pay1( int id1,int id2, double money) {
        // 先扣去用户1的钱
        addMoney(id1, -money);
        // 再添加用户2的钱
        addMoney(id2, money);
        return String.format("%s向%s转账%s", id1, id2, money);

    }

    // id1支付给id2，测试时，只要id2不存在，就会异常，id1的钱也不会少
    //  throw new RuntimeException，事务生效
    @Transactional
    public String pay2( int id1,int id2, double money) {
        try {
            // 先扣去用户1的钱
            addMoney(id1,-money);
            // 再添加用户2的钱
            addMoney(id2,money);
            return String.format("%s向%s转账%s", id1, id2, money);
        }catch (Exception ex) {
            System.out.println(ex.getMessage());
            throw new RuntimeException(String.format("%s向%s转账异常:%s",id1,id2,ex.getMessage()));
        }
    }


    //  rollbackFor指定Exception回滚， 事务有效，会回滚
    @Transactional(rollbackFor = Exception.class)
    public String pay3( int id1,int id2, double money) throws  Exception {

        try {
            // 先扣去用户1的钱
            addMoney(id1,-money);
            // 再添加用户2的钱
            addMoney(id2,money);
            return String.format("%s向%s转账%s", id1, id2, money);
        }catch (Exception ex) {
            System.out.println(ex.getMessage());
            throw new Exception(String.format("%s向%s转账异常:%s",id1,id2,ex.getMessage()));
        }
    }


    // throw new Exception，事务失效，不会回滚
    @Transactional
    public String payError1( int id1,int id2, double money) throws  Exception {
        try {
            // 先扣去用户1的钱
            addMoney(id1,-money);
            // 再添加用户2的钱
            addMoney(id2,money);
            return String.format("%s向%s转账%s", id1, id2, money);
        }catch (Exception ex) {
            System.out.println(ex.getMessage());
            throw new Exception(String.format("%s向%s转账异常:%s",id1,id2,ex.getMessage()));  // 不会回滚
        }
    }


    //  noRollbackFor指定RuntimeException不回滚，即使针对RuntimeException异常，也不会回滚，事务失效
    @Transactional(noRollbackFor = RuntimeException.class)
    public String payError2( int id1,int id2, double money) {
        try {
            // 先扣去用户1的钱
            addMoney(id1,-money);
            // 再添加用户2的钱
            addMoney(id2,money);
            return String.format("%s向%s转账%s", id1, id2, money);
        }catch (Exception ex) {
            System.out.println(ex.getMessage());
            throw new RuntimeException(String.format("%s向%s转账异常:%s",id1,id2,ex.getMessage()));
        }
    }
}


